package com.study.juc.thread;

import java.util.Random;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

/**
 * @program: juc-study
 * @author: jzhou
 * @date: 2022-08-17 18:15
 * @version: 1.0
 * @description: 演示 ThreadLocal 如何持有局部变量
 **/
public class ThreadLocalDemo {
	public static void main(String[] args) throws InterruptedException {
		House house = new House();
		House house1 = new House();
		threadDemo(house);
		// 线程池演示不调用remove方法问题
//		threadPoolDemo(house, house1);
	}

	private static void threadPoolDemo(House house, House house1) {
		ExecutorService executorService = Executors.newFixedThreadPool(3);
		for (int i = 0; i < 10; i++) {
			executorService.submit(()->{
//				try {
					int sale = new Random().nextInt(5) + 1;
				    Integer init = House.saleVolume.get();
					for (int j = 0; j < sale; j++) {
						house.saleVolumeByThreadLocal();
					}
					System.out.println(Thread.currentThread().getName() +" 初始值 ："+ init +" 号销售房源1："+ House.saleVolume.get());
//				} finally {
//					House.saleVolume.remove();
//				}
			});
		}

		for (int i = 0; i < 10; i++) {
			executorService.submit(()->{
				try {
					int sale = new Random().nextInt(5) + 1;
					Integer init = house1.saleVolume.get();
					for (int j = 0; j < sale; j++) {
						house1.saleVolumeByThreadLocal();
					}
					System.out.println(Thread.currentThread().getName() +" 初始值 ："+ init +" 号销售房源2："+ house1.saleVolume.get());
				} finally {
					House.saleVolume.remove();
				}
			});
		}
		executorService.shutdown();
	}

	/**
	 * 正常演示
	 * @param house
	 * @throws InterruptedException
	 */
	private static void threadDemo(House house) throws InterruptedException {
		for (int i = 0; i < 5; i++) {
			new Thread(()->{
				try {
					int sale = new Random().nextInt(5) + 1;
//				System.out.println(Thread.currentThread().getName() +"\t 卖出："+sale);
					for (int j = 0; j < sale; j++) {
						house.saleHouse();
						house.saleVolumeByThreadLocal();
					}
//				System.out.println(Thread.currentThread().getName() +" 号销售卖出："+house.saleCount); 只能拿到总数
					System.out.println(Thread.currentThread().getName() +" 号销售卖出："+ House.saleVolume.get());
				} finally {
					House.saleVolume.remove();
				}
			},String.valueOf(i)).start();
		}
		TimeUnit.MILLISECONDS.sleep(500);
		System.out.println(Thread.currentThread().getName()+"一共卖出" + house.saleCount);
	}
}


class House{
	//传统方法，只能实现对资源类得总体统计
	int saleCount = 0;
	public synchronized void saleHouse(){
		saleCount++;
	}

	// 使用 threadLocal
	static ThreadLocal<Integer> saleVolume = ThreadLocal.withInitial(() -> 0);
	public void saleVolumeByThreadLocal(){
		saleVolume.set(saleVolume.get() + 1);
	}

	static ThreadLocal<Integer> test = new ThreadLocal<>();

}
